package com.stkouyu.xiansheng;

import android.content.Context;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.constraint.AudioTypeForEvaEnum;
import com.constraint.CoreProvideTypeEnum;
import com.constraint.OffLineSourceEnum;
import com.constraint.ResultBody;
import com.google.gson.Gson;
import com.stkouyu.LancooSkEgnManager;
import com.stkouyu.listener.OnLancooSpeechRecognitionListener;
import com.stkouyu.xiansheng.entity.RecordResult;
import com.stkouyu.xiansheng.entity.SoundResult;
import com.stkouyu.xiansheng.entity.warrent.WarrantEntity;
import com.stkouyu.xiansheng.net.HttpCallback;
import com.stkouyu.xiansheng.net.HttpsUtils;
import com.xs.SingEngine;
import com.xs.impl.OnRealTimeResultListener;
import com.xs.utils.AiUtil;
import com.xs.utils.MD5Utils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;

/**
 * Created by pengmi on 2020/10/14 13:56
 * Description:
 */
public class SSoundManager {


    private static SSoundManager mSSoundManager;
    private Context mContext;
    private SingEngine mSingEngine;
    private int volume;

    private SSoundManager(Context context) {
        this.mContext = context.getApplicationContext();
        initSSoundEngine();
    }

    public static SSoundManager getInstance(Context context) {
        return mSSoundManager == null ? (mSSoundManager = new SSoundManager(context)) : mSSoundManager;
    }

    public static void release(){
        if(mSSoundManager!=null){
            mSSoundManager=null;
        }
    }

    /**
     * 初始化先声引擎
     * @param callBack 回调
     */
    public void initSSoundEngine(RequestWarrantIdCallBack callBack){
        Thread   mThread = new Thread() {
            @Override
            public void run() {
                try {
                    //  获取引擎实例,设置测评监听对象
                    mSingEngine = SingEngine.newInstance(mContext);
                    //  设置引擎类型
                    mSingEngine.setServerType(CoreProvideTypeEnum.CLOUD);
                    mSingEngine.setWavPath(AiUtil.getFilesDir(
                           mContext.getApplicationContext()).getPath()
                            + "/record_temp/"); // 构建引擎初始化参数
                    mSingEngine.setOffLineSource(OffLineSourceEnum.SOURCE_EN);
                    JSONObject cfg_init = mSingEngine.buildInitJson(
                            Config.APPKEY, Config.SECERTKEY);
                    //   设置引擎初始化参数
                    mSingEngine.setNewCfg(cfg_init);
                    mSingEngine.setWarrantIdNeedUpdateCallback(() -> getWarrantId(callBack));
                    //   引擎初始化
                    mSingEngine.createEngine();
                    getWarrantId(callBack);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        mThread.start();
    }

    /**
     * 初始化先声引擎
     */
    public void initSSoundEngine(){
        initSSoundEngine(new RequestWarrantIdCallBack() {
            @Override
            public void requestWarrantId(ResponseWarrantIdCallBack callBack) {
                String app_secret= Config.SECERTKEY;
                String appid= Config.APPKEY;
                String user_id= Config.USER_ID;
                String timestamp=System.currentTimeMillis()/1000+"";
                String user_client_ip="223.166.97.235";
                String warrant_available="14400";
                String param_ordered_string = "app_secret="+app_secret+"&appid="+
                        appid+"&timestamp="+timestamp+"&user_client_ip="+user_client_ip+"&user_id="+user_id;

                Log.e("eeee","加密后的sign:"+ MD5Utils.getStrMD5(param_ordered_string));

                HashMap<String, String> map = new HashMap<>();
                map.put("appid", appid);
                map.put("timestamp", timestamp);
                map.put("user_id", user_id);
                map.put("user_client_ip", user_client_ip);
                map.put("request_sign", MD5Utils.getStrMD5(param_ordered_string));
                map.put("warrant_available",warrant_available);
                Log.e("pm","initSSoundEngine start ");
                HttpsUtils.requestUrl(Config.Get_WARRANT_ID, map, new HttpCallback() {
                    @Override
                    public void onSuccess(String result) {
                        if (!TextUtils.isEmpty(result)) {
//                    WarrantEntity warrantEntity = new Gson().fromJson(result, WarrantEntity.class);
                            WarrantEntity warrantEntity = getWarrantEntity(result);
                            if (warrantEntity.code == 0 && TextUtils.equals("success", warrantEntity.message)) {
                                WarrantEntity.WarrantDetailEntity data = warrantEntity.data;
//                                mSingEngine.setAuthInfo(data.warrantId, data.expireAt);
                                callBack.responseWarrantID(data.warrantId, data.expireAt);
                                Log.e("pm","initSSoundEngine onNext 鉴权信息获取成功");
                            } else {
                                Log.e("pm","initSSoundEngine onError 鉴权信息获取失败 onFaild"+result);
                            }
                        }
                    }

                    @Override
                    public void onFaild() {
                        Log.e("pm","initSSoundEngine onError 鉴权信息获取失败 onFaild222");
                    }
                });



            }
        });
    }


    private WarrantEntity getWarrantEntity(String result) {
        WarrantEntity warrantEntity = new WarrantEntity();
        try {
            JSONObject jsonObject = new JSONObject(result);
            int code = jsonObject.optInt("code");
            String message = jsonObject.optString("message");
            warrantEntity.code = code;
            warrantEntity.message = message;

            JSONObject data = jsonObject.optJSONObject("data");
            WarrantEntity.WarrantDetailEntity warrantDetailEntity = new WarrantEntity.WarrantDetailEntity();
            long expireAt = data.optLong("expire_at");
            String warrantId = data.optString("warrant_id");
            warrantDetailEntity.expireAt = expireAt;
            warrantDetailEntity.warrantId = warrantId;
            warrantEntity.data = warrantDetailEntity;

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return warrantEntity;
    }


    private void getWarrantId(RequestWarrantIdCallBack callBack){
        if(callBack!=null){
            callBack.requestWarrantId((warrandID, outTime) -> {
                if(mSingEngine!=null){
                    Log.e("eeee","获取鉴权信息成功啦");
                    mSingEngine.setAuthInfo(warrandID, outTime);
                }
            });
        }
    }

    /**
     * 开始语音评测
     * @param content 评测内容
     * @param url 音频url
     * @param mHandler 回调消息发送器
     * @param onLancooRecordListener listener
     */
    public void startRecord(String content, String url, Handler mHandler, LancooSkEgnManager.OnLancooRecordListener onLancooRecordListener) {
        volume=0;
        try {
            JSONObject request = new JSONObject();
            request.put("coreType", Config.TYPE_SENT)
                    .put("refText", content)
                    .put("rank", 100);
            JSONObject cfg = mSingEngine.buildStartJson(Config.USER_ID, request);
            mSingEngine.setListener(new OnRealTimeResultListener() {
                @Override
                public void onRealTimeEval(JSONObject jsonObject) {

                }

                @Override
                public void onBegin() {
                    Message message=new Message();
                    message.what=105;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onResult(JSONObject jsonObject) {
                    Log.e("eeee","评测成功啦");
                    try{
                        String refText = jsonObject.getString("refText");
                        String audioUrl = jsonObject.getString("audioUrl");
                        String result = jsonObject.getString("result");
                        Log.e("vvvvv",refText+"\n"+audioUrl+"\n"+result);
//                        et_result.setText(refText+"\n"+audioUrl+"\n"+result);
                        Gson gson=new Gson();
                        SoundResult soundResult = gson.fromJson(result, SoundResult.class);
                        soundResult.setRecordUrl(url);
                        Message message=new Message();
                        message.what=100;
                        message.arg1= (int) soundResult.getOverall();
                        message.obj=soundResult;
                        mHandler.sendMessage(message);
//                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        Log.e("eeee","Exception,Exception,Exception:"+e.toString());
                        Message message=new Message();
                        message.what=101;
                        message.obj=e.toString();
                        mHandler.sendMessage(message);
                        cancelRecord();
                    }
                }

                @Override
                public void onEnd(ResultBody resultBody) {
                    if(resultBody!=null&&resultBody.getCode()==0){
                        return;
                    }
                    Log.e("eeee","onEnd,onEnd,onEnd:");
                    Message message=new Message();
                    message.what=101;
                    message.arg1=resultBody.getCode();
                    mHandler.sendMessage(message);
                    cancelRecord();
                }

                @Override
                public void onUpdateVolume(int i) {
                    volume=i;
                    Log.e("eeee","onUpdateVolume:"+i);
                    Message message=new Message();
                    message.what=110;
                    message.arg1=i;
                    mHandler.sendMessage(message);
//                    if(onLancooRecordListener!=null){
//                        onLancooRecordListener.onRecording(0,i);
//                    }
                }

                @Override
                public void onFrontVadTimeOut() {

                }

                @Override
                public void onBackVadTimeOut() {

                }

                @Override
                public void onRecordingBuffer(byte[] bytes, int i) {

                }

                @Override
                public void onRecordLengthOut() {

                }

                @Override
                public void onReady() {

                }

                @Override
                public void onPlayCompeleted() {

                }

                @Override
                public void onRecordStop() {
                    Log.e("onTouch","onRecordStop");
                    Message message=new Message();
                    message.what=109;
                    mHandler.sendMessage(message);

                }
            });
            mSingEngine.setStartCfg(cfg);
            mSingEngine.setChannel(1);
//            mSingEngine.start();
            if(!TextUtils.isEmpty(url)){
                mSingEngine.setWavPath(url);
            }
            mSingEngine.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 开始语音识别
     * @param url 音频url
     * @param recognitionType 类型 0-英文 ，1-中文
     * @param mHandler 回调消息发送器
     * @param onLancooSpeechRecognitionListener listener
     */
    public void startRecognition(String url,int recognitionType, Handler mHandler,
                                 OnLancooSpeechRecognitionListener onLancooSpeechRecognitionListener){
        try {
            JSONObject request = new JSONObject();
            String coreType;
            if(recognitionType==0){
                coreType= Config.TYPE_EN_SENTENCE_REC;
            }else{
                coreType= Config.TYPE_CN_SENTENCE_REC;
            }
            request.put("coreType", coreType)
                    .put("rank", 100);
            mSingEngine.setSampleRate(16000L);
            mSingEngine.setAudioTypeForEva(AudioTypeForEvaEnum.WAV);
            JSONObject cfg = mSingEngine.buildStartJson(Config.USER_ID, request);
            mSingEngine.setListener(new OnRealTimeResultListener() {
                @Override
                public void onRealTimeEval(JSONObject jsonObject) {

                }

                @Override
                public void onBegin() {
                    Message message=new Message();
                    message.what=105;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onResult(JSONObject jsonObject) {
                    Log.e("eeee","评测成功啦");
                    try{
//                        String refText = jsonObject.getString("refText");
                        String audioUrl = jsonObject.getString("audioUrl");
                        String result = jsonObject.getString("result");
                        Log.e("vvvvv","\n"+audioUrl+"\n"+result);
//                        et_result.setText(refText+"\n"+audioUrl+"\n"+result);
                        Gson gson=new Gson();
                        SoundResult soundResult = gson.fromJson(result, SoundResult.class);
                        soundResult.setRecordUrl(url);
                        soundResult.setRecognitionType(recognitionType);
                        Message message=new Message();
                        message.what=100;
                        message.arg1= (int) soundResult.getOverall();
                        message.obj=soundResult;
                        mHandler.sendMessage(message);
//                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        SoundResult soundResult=new SoundResult();
                        soundResult.setRecordUrl(url);
                        Message message=new Message();
                        message.what=104;
                        message.obj=soundResult;
                        mHandler.sendMessage(message);
//                        if(onLancooSpeechRecognitionListener!=null){
//                            onLancooSpeechRecognitionListener.onSpeechRecognitionError(""+e.toString());
//                        }
                    }
                }

                @Override
                public void onEnd(ResultBody resultBody) {
                    if(resultBody!=null&&resultBody.getCode()==0){
                        return;
                    }
                    Log.e("eeee","onEnd,onEnd,onEnd:"+new Gson().toJson(resultBody));
                    Message message=new Message();
                    message.what=101;
                    message.arg1=resultBody.getCode();
                    mHandler.sendMessage(message);
                    cancelRecord();
                }

                @Override
                public void onUpdateVolume(int i) {
                    volume=i;
                    Message message=new Message();
                    message.what=110;
                    message.arg1=i;
                    mHandler.sendMessage(message);
//                    Log.e("eeee","onUpdateVolume:"+i);
//                    if(onLancooSpeechRecognitionListener!=null){
//                        onLancooSpeechRecognitionListener.onSpeechRecogniting(0,i);
//                    }
                }

                @Override
                public void onFrontVadTimeOut() {

                }

                @Override
                public void onBackVadTimeOut() {

                }

                @Override
                public void onRecordingBuffer(byte[] bytes, int i) {

                }

                @Override
                public void onRecordLengthOut() {

                }

                @Override
                public void onReady() {

                }

                @Override
                public void onPlayCompeleted() {

                }

                @Override
                public void onRecordStop() {

                }
            });
            mSingEngine.setStartCfg(cfg);
            mSingEngine.setChannel(1);
//            mSingEngine.start();
            if(!TextUtils.isEmpty(url)){
                mSingEngine.setWavPath(url);
            }
            Log.e("eeee","本地url:"+url);
            mSingEngine.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**********************************************************************/
    /**
     * add by 王国龙
     * 开始语音识别
     * @param url 音频url
     * @param recognitionType 类型 0-英文 ，1-中文
     * @param mHandler 回调消息发送器
     * @param onLancooSpeechRecognitionListener listener
     */
    public void startCtfdRecognition(String url,int recognitionType, Handler mHandler,
                                 OnLancooSpeechRecognitionListener onLancooSpeechRecognitionListener){
        try {
            JSONObject request = new JSONObject();
            String coreType;
            if(recognitionType==0){
                coreType= Config.TYPE_EN_SENTENCE_REC;
            }else{
                coreType= Config.TYPE_CN_SENTENCE_REC;
            }
            request.put("coreType", coreType)
                    .put("rank", 100);
            JSONObject cfg = mSingEngine.buildStartJson(Config.USER_ID, request);
            mSingEngine.setListener(new OnRealTimeResultListener() {
                @Override
                public void onRealTimeEval(JSONObject jsonObject) {

                }

                @Override
                public void onBegin() {
                    Message message=new Message();
                    message.what=105;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onResult(JSONObject jsonObject) {
                    Log.e("onResult","识别成功啦"+jsonObject);
                    try{
                        Gson gson = new Gson();
                        RecordResult recordResult = gson.fromJson(String.valueOf(jsonObject), RecordResult.class);
                        String Sentence = "";
                        int Size = recordResult.getResult().getWrd_details().size();
                        for (int a = 0; a < Size; a++) {
                            String Word = recordResult.getResult().getWrd_details().get(a).getCharX();
                            Sentence = Sentence + " " + Word;
                        }
                        Log.e("=onResultXX=", "======AA****识别内容========" + Sentence);
                        onLancooSpeechRecognitionListener.onSpeechRecognitionEnd(Sentence,jsonObject.getString("audioUrl"));
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }

                @Override
                public void onEnd(ResultBody resultBody) {
                    if(resultBody!=null&&resultBody.getCode()==0){
                        return;
                    }
                    cancelRecord();
                }

                @Override
                public void onUpdateVolume(int i) {
                    volume=i;
                    Log.e("eeee","onUpdateVolume:"+i);
//                    if(onLancooSpeechRecognitionListener!=null){
//                        onLancooSpeechRecognitionListener.onSpeechRecogniting(0,i);
//                    }
                    Message message=new Message();
                    message.what=110;
                    message.arg1=i;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onFrontVadTimeOut() {

                }

                @Override
                public void onBackVadTimeOut() {

                }

                @Override
                public void onRecordingBuffer(byte[] bytes, int i) {

                }

                @Override
                public void onRecordLengthOut() {

                }

                @Override
                public void onReady() {

                }

                @Override
                public void onPlayCompeleted() {

                }

                @Override
                public void onRecordStop() {

                }
            });
            mSingEngine.setStartCfg(cfg);
            mSingEngine.setChannel(1);
//            mSingEngine.start();
            if(!TextUtils.isEmpty(url)){
                mSingEngine.setWavPath(url);
            }
            Log.e("eeee","本地url:"+url);
            mSingEngine.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**********************************************************************/

    /**
     * 开始本地音频导入语音识别
     * @param url 本地音频url
     * @param recognitionType 类型 0-英文 ，1-中文
     * @param mHandler 回调消息发送器
     * @param onLancooSpeechRecognitionListener listener
     */
    public void startFileImportRecognition(String url,int recognitionType, Handler mHandler,
                                 OnLancooSpeechRecognitionListener onLancooSpeechRecognitionListener){

        try {
            JSONObject request = new JSONObject();
            String coreType;
            if(recognitionType==0){
                coreType= Config.TYPE_EN_SENTENCE_REC;
            }else{
                coreType= Config.TYPE_CN_SENTENCE_REC;
            }
            request.put("coreType", coreType)
                    .put("rank", 100);
            mSingEngine.setAudioTypeForEva(AudioTypeForEvaEnum.MP3);
            MediaExtractor mex = new MediaExtractor();
            try {
                mex.setDataSource(url);// the adresss location of the sound on sdcard.
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            MediaFormat mf = mex.getTrackFormat(0);
            int bitRate = mf.getInteger(MediaFormat.KEY_BIT_RATE);
            int sampleRate = mf.getInteger(MediaFormat.KEY_SAMPLE_RATE);
            int channelCount = mf.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
            Log.e("eee","采样率："+sampleRate);
            Log.e("eee","比特率："+bitRate);
            Log.e("eee","声道："+channelCount);
            if(bitRate!=sampleRate){
                mSingEngine.setSampleRate(sampleRate);
            }
            JSONObject cfg = mSingEngine.buildStartJson(Config.USER_ID, request);
            mSingEngine.setListener(new OnRealTimeResultListener() {
                @Override
                public void onRealTimeEval(JSONObject jsonObject) {

                }

                @Override
                public void onBegin() {
                    Message message=new Message();
                    message.what=105;
                    mHandler.sendMessage(message);
                }

                @Override
                public void onResult(JSONObject jsonObject) {
                    Log.e("eeee","评测成功啦");
                    try{
//                        String refText = jsonObject.getString("refText");
                        String audioUrl = jsonObject.getString("audioUrl");
                        String result = jsonObject.getString("result");
                        Log.e("vvvvv","\n"+audioUrl+"\n"+result);
//                        et_result.setText(refText+"\n"+audioUrl+"\n"+result);
                        Gson gson=new Gson();
                        SoundResult soundResult = gson.fromJson(result, SoundResult.class);
                        soundResult.setRecordUrl(url);
                        soundResult.setRecognitionType(recognitionType);
                        Message message=new Message();
                        message.what=100;
                        message.arg1= (int) soundResult.getOverall();
                        message.obj=soundResult;
                        mHandler.sendMessage(message);
//                        }
                    }catch (Exception e){
                        Log.e("eeee","Exception,Exception");
                        e.printStackTrace();
                        SoundResult soundResult=new SoundResult();
                        soundResult.setRecordUrl(url);
                        Message message=new Message();
                        message.what=104;
                        message.obj=soundResult;
                        mHandler.sendMessage(message);
//                        if(onLancooSpeechRecognitionListener!=null){
//                            onLancooSpeechRecognitionListener.onSpeechRecognitionError(""+e.toString());
//                        }
                    }
                }

                @Override
                public void onEnd(ResultBody resultBody) {
                    if(resultBody!=null&&resultBody.getCode()==0){
                        return;
                    }
                    Log.e("eeee","onEnd,onEnd,onEnd");
                    Message message=new Message();
                    message.what=101;
                    message.arg1=resultBody.getCode();
                    mHandler.sendMessage(message);
                }

                @Override
                public void onUpdateVolume(int i) {
                    volume=i;
                    Message message=new Message();
                    message.what=110;
                    message.arg1=i;
                    mHandler.sendMessage(message);
                    Log.e("eeee","onUpdateVolume:"+i);
//                    if(onLancooSpeechRecognitionListener!=null){
//                        onLancooSpeechRecognitionListener.onSpeechRecogniting(0,i);
//                    }
                }

                @Override
                public void onFrontVadTimeOut() {

                }

                @Override
                public void onBackVadTimeOut() {

                }

                @Override
                public void onRecordingBuffer(byte[] bytes, int i) {

                }

                @Override
                public void onRecordLengthOut() {

                }

                @Override
                public void onReady() {

                }

                @Override
                public void onPlayCompeleted() {

                }

                @Override
                public void onRecordStop() {

                }
            });
            mSingEngine.setStartCfg(cfg);
            mSingEngine.setChannel(1);
////            mSingEngine.start();
//            if(!TextUtils.isEmpty(url)){
//                mSingEngine.setWavPath(url);
//            }
            mSingEngine.startWithPCM(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 结束评测，执行识别回调
     */
    public void stopRecord(){
        if(mSingEngine==null){
            return;
        }
        mSingEngine.stop();
    }

    /**
     * 取消评测
     */
    public void cancelRecord(){
        if(mSingEngine==null){
            return;
        }
        mSingEngine.cancel();
    }

    public int getVolume(){
        return this.volume;
    }

}
